package com.mihuo.util;

import cn.hutool.core.map.MapUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.Method;
import cn.hutool.json.JSONUtil;

import java.util.List;
import java.util.Map;

/**
 * Elasticsearch HTTP 工具类，使用 ES 原生 HTTP API 操作索引与文档。
 * 依赖 Hutool 工具库。
 */
public class EsHttpUtil {

    private static String ES_HOST = "http://localhost:9200";

    /**
     * 设置 ES 服务地址
     * @param host 例如：http://localhost:9200
     */
    public static void setEsHost(String host) {
        ES_HOST = host;
    }

    private static HttpRequest buildRequest(String method, String url) {
        return HttpRequest.of(url).method(Method.valueOf(method))
                .header("Content-Type", "application/json");
    }

    /**
     * 判断索引是否存在
     * @param indexName 索引名
     * @return true=存在，false=不存在
     */
    public static boolean indexExists(String indexName) {
        HttpResponse response = buildRequest("HEAD", ES_HOST + "/" + indexName).execute();
        return response.getStatus() == 200;
    }

    /**
     * 创建索引并设置 mapping 映射结构
     * @param indexName 索引名
     * @param mappingJson mapping JSON
     * 示例:
     * {
     *   "mappings": {
     *     "properties": {
     *       "title": {"type": "text"},
     *       "age": {"type": "integer"}
     *     }
     *   }
     * }
     * @return ES 返回结果
     */
    public static String createIndex(String indexName, String mappingJson) {
        return buildRequest("PUT", ES_HOST + "/" + indexName)
                .body(mappingJson)
                .execute()
                .body();
    }

    /**
     * 创建带有 analyzer 分词器的索引
     * @param indexName 索引名
     * @param analyzerJson 分词器定义
     * 示例:
     * {
     *   "settings": {
     *     "analysis": {
     *       "analyzer": {
     *         "my_analyzer": {
     *           "type": "standard"
     *         }
     *       }
     *     }
     *   }
     * }
     * @return 创建结果
     */
    public static String createIndexWithAnalyzer(String indexName, String analyzerJson) {
        return buildRequest("PUT", ES_HOST + "/" + indexName)
                .body(analyzerJson)
                .execute()
                .body();
    }

    /**
     * 删除索引
     * @param indexName 索引名
     * @return 删除结果
     */
    public static String deleteIndex(String indexName) {
        return buildRequest("DELETE", ES_HOST + "/" + indexName).execute().body();
    }

    /**
     * 插入文档（自动生成 ID）
     * @param index 索引名
     * @param jsonStr 文档内容
     * 示例:
     * Map.of("title", "Elasticsearch 入门", "views", 100)
     * @return 插入结果
     */
    public static String insertDoc(String index, String jsonStr) {
        return buildRequest("POST", ES_HOST + "/" + index + "/_doc")
                .body(jsonStr)
                .execute()
                .body();
    }

    /**
     * 插入文档（指定 ID）
     * @param index 索引名
     * @param id 文档 ID
     * @param doc 文档内容
     * @return 插入结果
     */
    public static String insertDocWithId(String index, String id, Map<String, Object> doc) {
        return buildRequest("PUT", ES_HOST + "/" + index + "/_doc/" + id)
                .body(JSONUtil.toJsonStr(doc))
                .execute()
                .body();
    }

    /**
     * 获取文档
     * @param index 索引名
     * @param id 文档 ID
     * @return 查询结果
     */
    public static String getDocById(String index, String id) {
        return buildRequest("GET", ES_HOST + "/" + index + "/_doc/" + id).execute().body();
    }

    /**
     * 删除文档
     * @param index 索引名
     * @param id 文档 ID
     * @return 删除结果
     */
    public static String deleteDoc(String index, String id) {
        return buildRequest("DELETE", ES_HOST + "/" + index + "/_doc/" + id).execute().body();
    }

    /**
     * 更新文档（部分字段）
     * @param index 索引名
     * @param id 文档 ID
     * @param doc 要更新的字段内容
     * @return 更新结果
     */
    public static String updateDocById(String index, String id, Map<String, Object> doc) {
        String url = ES_HOST + "/" + index + "/_update/" + id;
        String body = JSONUtil.toJsonStr(MapUtil.of("doc", doc));
        return buildRequest("POST", url).body(body).execute().body();
    }

    /**
     * DSL 搜索
     * @param index 索引名
     * @param dslJson 搜索 DSL
     * @return 查询结果
     */
    public static String search(String index, String dslJson) {
        return buildRequest("POST", ES_HOST + "/" + index + "/_search")
                .body(dslJson)
                .execute()
                .body();
    }

    /**
     * 高亮搜索
     * @param index 索引名
     * @param keyword 关键词
     * @param field 字段名
     * @return 高亮搜索结果
     */
    public static String highlightSearch(String index, String keyword, String field) {
        String dsl = "{ \"query\": { \"match\": { \"" + field + "\": \"" + keyword + "\" } }, " +
                "\"highlight\": { \"fields\": { \"" + field + "\": {} } } }";
        return search(index, dsl);
    }

    /**
     * 统计数量
     * @param index 索引名
     * @param queryJson 查询条件
     * @return 数量统计结果
     */
    public static String count(String index, String queryJson) {
        return buildRequest("POST", ES_HOST + "/" + index + "/_count")
                .body(queryJson)
                .execute()
                .body();
    }

    /**
     * 批量插入文档
     * @param index 索引名
     * @param docs 文档列表
     * @return 批量插入结果
     */
    public static String bulkInsertDocs(String index, List<Map<String, Object>> docs) {
        StringBuilder bulkBody = new StringBuilder();
        for (Map<String, Object> doc : docs) {
            bulkBody.append("{ \"index\": { \"_index\": \"").append(index).append("\" } }\n");
            bulkBody.append(JSONUtil.toJsonStr(doc)).append("\n");
        }
        return buildRequest("POST", ES_HOST + "/_bulk")
                .body(bulkBody.toString())
                .execute()
                .body();
    }

    /**
     * 批量删除文档
     * @param index 索引名
     * @param ids ID 列表
     * @return 批量删除结果
     */
    public static String bulkDeleteDocs(String index, List<String> ids) {
        StringBuilder bulkBody = new StringBuilder();
        for (String id : ids) {
            bulkBody.append("{ \"delete\": { \"_index\": \"").append(index).append("\", \"_id\": \"").append(id).append("\" } }\n");
        }
        return buildRequest("POST", ES_HOST + "/_bulk")
                .body(bulkBody.toString())
                .execute()
                .body();
    }

    /**
     * Scroll 查询（首次 scroll）
     * @param index 索引名
     * @param queryJson DSL 查询
     * @param scrollTime 滚动时间，例如"1m"
     * @return 查询结果（包含 _scroll_id）
     */
    public static String scrollSearch(String index, String queryJson, String scrollTime) {
        String url = ES_HOST + "/" + index + "/_search?scroll=" + scrollTime;
        HttpResponse response = buildRequest("POST", url)
                .body(queryJson)
                .execute();
        return response.body();
    }

    /**
     * 获取下一页 Scroll 查询
     * @param scrollId 上一次的 _scroll_id
     * @param scrollTime 滚动时间
     * @return 下一页数据
     */
    public static String scrollNext(String scrollId, String scrollTime) {
        String url = ES_HOST + "/_search/scroll";
        String body = "{\"scroll\": \"" + scrollTime + "\", \"scroll_id\": \"" + scrollId + "\"}";
        return buildRequest("POST", url)
                .body(body)
                .execute()
                .body();
    }

}
